package com.zhuiyun.project.api.frontuser.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import com.google.gson.Gson;
import com.zhuiyun.project.api.tag.entity.Tag;
import com.zhuiyun.project.api.frontuser.entity.FrontUser;
import com.zhuiyun.project.api.frontuser.mapper.FrontUserMapper;
import com.zhuiyun.project.api.frontuser.model.FrontUserModel;
import com.zhuiyun.project.api.headportrait.entity.SysHeadPortrait;
import com.zhuiyun.project.api.frontuser.service.FrontUserService;
import com.zhuiyun.project.api.headportrait.mapper.HeadPortraitMapper;
import com.zhuiyun.project.api.system.login.model.LoginDTO;
import com.zhuiyun.project.common.errorCode.CommonException;
import com.zhuiyun.project.common.errorCode.EmErrorCode;
import com.zhuiyun.project.common.response.CommonResult;
import com.zhuiyun.project.utils.BeanUtils;
import com.zhuiyun.project.utils.ObjectUtils;
import com.zhuiyun.project.utils.StringUtils;
import com.zhuiyun.project.utils.UploadFileUtils;
import com.zhuiyun.project.utils.constants.CommonConstants;
import com.zhuiyun.project.utils.pageUtil.MybatisPageHelper;
import com.zhuiyun.project.utils.pageUtil.PageRequest;
import com.zhuiyun.project.utils.validator.ValidatorUtil;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;
import com.zhuiyun.project.utils.pageUtil.PageResult;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;

/**
 * @ClassName FrontUserServiceImpl
 * @Description TODO
 * @Author XMY
 * @Date 2023/12/11 10:59
 **/
@Service
public class FrontUserServiceImpl implements FrontUserService {
    @Autowired
    private HeadPortraitMapper headPortraitMapper;
    @Autowired
    private FrontUserMapper frontUserMapper;
    @Autowired
    private RestTemplate restTemplate;
    @Value("${APPID}")
    private String appid;
    @Value("${APPSECRET}")
    private String appsecret;
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;
    @Resource
    BCryptPasswordEncoder passwordEncoder;

    /**
     * @Author XMY
     * @Description 前端头像上传
     * @Date 2023/12/11 11:02
     * @Return
     * @param file
     */
    @Override
    public CommonResult headPortraitUpload(MultipartFile file) {
        String originalFilename = file.getOriginalFilename();
        String type = FileUtil.extName(originalFilename);
        long size = file.getSize();
        String uploadFiles =  UploadFileUtils.uploadFile(file);
        Integer uploadFileId = Integer.parseInt(uploadFiles);
        String url = "http://101.43.223.224:8765/image/getImageById?id=" + uploadFiles;
        SysHeadPortrait sysHeadPortrait = new SysHeadPortrait();
        sysHeadPortrait.setPortraitName(originalFilename);
        sysHeadPortrait.setPortraitType(type);
        sysHeadPortrait.setPortraitSize(size/1024);
        sysHeadPortrait.setPortraitUrl(url);
        sysHeadPortrait.setPicId(uploadFileId);
        sysHeadPortrait.setCreateTime(new Date());
        headPortraitMapper.insert(sysHeadPortrait);
        return CommonResult.ok(uploadFiles);
    }
    /**
     * @Author XMY
     * @Description 修改用户信息
     * @Date 2023/12/11 16:11
     * @Return
     * @param frontUserModel
     */
    @Override
    public CommonResult updateFrontUser(FrontUserModel frontUserModel) throws CommonException {
        Date date = new Date();
        frontUserModel.setUpdateTime(date);
        if (ValidatorUtil.ValidationObject(frontUserModel)) {
            if(StringUtils.isEmpty(frontUserModel.getAvatarId())){
                List<SysHeadPortrait> headPortraitList = headPortraitMapper.selectAll();
                if (headPortraitList != null && !headPortraitList.isEmpty()) {
                    int lastIndex = headPortraitList.size() - 1;
                    SysHeadPortrait lastFile = headPortraitList.get(lastIndex);
                    frontUserModel.setAvatarId(lastFile.getPortraitUrl());
                }
            }
            FrontUser frontUser = new FrontUser();
            BeanUtils.copy(frontUserModel, frontUser);
            int i = frontUserMapper.updateFrontUser(frontUser);
            if (i > 0) {
                return CommonResult.ok(EmErrorCode.UPDATE_OK);
            } else {
                return CommonResult.ok(EmErrorCode.UPDATE_ERROR);
            }
        } else {
            return CommonResult.ok(EmErrorCode.UPDATE_ERROR);
        }
    }
    /**
     * @Author XMY
     * @Description 根据id用户信息
     * @Date 2023/12/12 8:28
     * @Return
     * @param userId
     */
    @Override
    public CommonResult getFrontUserById(Integer userId) throws CommonException {
        return CommonResult.ok(frontUserMapper.getFrontUserById(userId));
    }
    /**
     * @Author LYX
     * @Description 根据id用户信息
     * @Date 2023/3/6 8:48
     * @Return
     * @param userId
     */
    @Override
    public FrontUser getFrontUserByUserId(Integer userId) {
        return frontUserMapper.getFrontUserByUserId(userId);
    }
    /**
     * @Author LYX
     * @Description 根据用户名查询用户信息
     * @Date 2024/1/9 16:47
     */
    @Override
    public FrontUser getFrontUserByUserAccount(String userAccount) {
        FrontUser list  = frontUserMapper.getFrontUserByUserAccount(userAccount);
        return list;
    }
    /**
     * @Author LYX
     * @Description 根据id添加微信唯一标识openid
     * @Date 2024/3/4 19:47
     */
    @Override
    public Boolean updateOpenid(Integer id, String jg) {
        return frontUserMapper.updateOpenid(id,jg);
    }
    /**
     * @Author LYX
     * @Description 根据openid查询用户信息
     * @Date 2024/2/27 16:47
     */
    @Override
    public FrontUser getFrontUserByOpenId(String openid) {
        return frontUserMapper.getFrontUserByOpenId(openid);
    }
    /**
     * @Author LYX
     * @Description 微信登录（用户不存在）新增用户信息
     * @Date 2024/2/28 8:30
     */
    @Override
    public boolean insertFrontUser(FrontUser frontUser) {
        return frontUserMapper.insertFrontUser(frontUser);
    }
    /**
     * @Author XMY
     * @Description 根据用户id获取个性标签
     * @Date 2023/12/12 14:27
     * @Return
     * @param userId
     */
    @Override
    public CommonResult getTagListByUserId(Integer userId) {
        return CommonResult.ok(frontUserMapper.getTagListByUserId(userId));
    }
    /**
     * @Author LYX
     * @Description 用户添加个性标签
     * @Date 2024/3/5 19:27
     * @Return
     */
    @Override
    public int insertTag(Tag tag) {
        return frontUserMapper.insertTag(tag);
    }

    @Override
    public Boolean insertUserTag(int userid, int tagid) {
        return frontUserMapper.insertUserTag(userid,tagid);
    }
    /**
     * @Author LYX
     * @Description 用户添加邮箱
     * @Date 2024/3/8 8:50
     * @Return
     */
    @Override
    public Boolean updateEmail(String email,int userId) {
        return frontUserMapper.updateEmail(email,userId);
    }
    /**
    * @Author 雅俗共赏
    * @Description
    * @Date 2024/3/8 15:39
    * @Return
    *  根据用户的code获取openId
    */
    @Override
    public String CodeOpen(String code) {
        // 根据传入code，调用微信服务器，获取唯一openid 微信服务器接口地址
        String url = "https://api.weixin.qq.com/sns/jscode2session?appid="+appid+ "&secret="+appsecret
                +"&js_code="+ code +"&grant_type=authorization_code";
        String errmsg = "";
        String errcode = "";
        String session_key = "";
        String openid = "";
        LoginDTO loginDTO;
        // 发送请求
        ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.GET, null, String.class);
        // 判断请求是否成功
        if(responseEntity.getStatusCode() == HttpStatus.OK) {
            // 获取主要内容
            String sessionData = responseEntity.getBody();
            Gson gson = new Gson();
            //将json字符串转化为实体类;
            loginDTO = gson.fromJson(sessionData, LoginDTO.class);
            //获取用户的唯一标识openid
            openid = loginDTO.getOpenid();
            //获取错误码
            errcode = String.valueOf(loginDTO.getErrcode());
            //获取错误信息
            errmsg = loginDTO.getErrmsg();
        }
        return openid;
    }

    /**
     * @Author XMY
     * @Description 添加/修改用户信息邮箱校验
     * @Date 2023/12/15 14:00
     * @Return
     * @param email
     */
    @Override
    public CommonResult verifyEmail(String email){
        FrontUser frontUser = frontUserMapper.verifyEmail(email);
        if(frontUser != null){
            return CommonResult.error("邮箱已被绑定,请更换邮箱");
        }else{
            return CommonResult.ok();
        }
    }

    /**
     * @Author XMY
     * @Description 校验邮箱验证码
     * @Date 2023/12/13 14:22
     * @Return
     * @param email
     * @param code
     */
    @Override
    public CommonResult judgeCode(String email, String code) throws CommonException{
        if (StringUtils.isEmpty(email) || StringUtils.isEmpty(code)) {
            return CommonResult.error("邮箱或验证码不能为空");
        }
        List<FrontUser> frontUserList = frontUserMapper.getFrontUserEmailByEmail(email);
        if(!ValidatorUtil.ValidationObject(frontUserList)){
            return CommonResult.error("邮箱已被绑定！");
        }
        String cachedEmail = stringRedisTemplate.opsForValue().get(CommonConstants.CACHE_EMAIL + email);
        if (StringUtils.isEmpty(cachedEmail)) {
            return CommonResult.error("邮箱错误");
        }
        String cachedCode = stringRedisTemplate.opsForValue().get(CommonConstants.CACHE_EMAIL_CODE + code);
        if (code.equals(cachedCode)) {
            return CommonResult.error("验证码错误");
        }
        int userId = 2;
        // 验证通过，执行相关逻辑
        int i = frontUserMapper.updateEmail1(email, userId);
        if (i > 0) {
            return CommonResult.ok(EmErrorCode.UPDATE_OK);
        } else {
            return CommonResult.ok(EmErrorCode.UPDATE_ERROR);
        }
    }

    /**
     * @Author XMY
     * @Description 修改用户信息
     * @Date 2023/12/15 9:51
     * @Return
     * @param frontUserModel
     */
    @Override
    public CommonResult updateFrontUserById(FrontUserModel frontUserModel) throws CommonException{
        if (ValidatorUtil.ValidationObject(frontUserModel)) {
            FrontUser frontUser = new FrontUser();
            BeanUtils.copy(frontUserModel, frontUser);
            int i = frontUserMapper.updateFrontUser(frontUser);
            if (i > 0) {
                return CommonResult.ok(EmErrorCode.UPDATE_OK);
            } else {
                return CommonResult.ok(EmErrorCode.UPDATE_ERROR);
            }
        } else {
            return CommonResult.ok(EmErrorCode.UPDATE_ERROR);
        }
    }

    /**
     * @Author XMY
     * @Description 删除音频信息
     * @Date 2023/12/6 19:43
     * @Return
     * @param userId
     */
    @Override
    public CommonResult delFrontUserById(Integer[] userId) throws CommonException {
        int i = 0;
        boolean f = false;
        // 判断是否id为空
        if(ObjectUtils.isNotEmpty(userId)){
            for (Integer c : userId) {
                i = frontUserMapper.delFrontUserById(c);
            }
            if(i>0){
                return CommonResult.ok(EmErrorCode.DELETE_OK);
            }else{
                return CommonResult.ok(EmErrorCode.DELETE_ERROR);
            }
        }else{
            throw new CommonException(EmErrorCode.ID_NULL);
        }
    }

    @Override
    public CommonResult addFrontUser(FrontUserModel frontUserModel) throws CommonException{
        // 验证参数的规范性
        if (ValidatorUtil.ValidationObject(frontUserModel)) {
            FrontUser frontUser = new FrontUser();
            // frontUserModel 对象拷贝成 frontUser
            BeanUtils.copy(frontUserModel, frontUser);
            frontUser.setAvatarId("http://101.43.223.224:8765/image/getImageById?id=6553");
            frontUser.setUserPassword(bCryptPasswordEncoder.encode(frontUser.getUserPassword()));
            Date date = new Date();
            frontUser.setCreateTime(date);
            int i = frontUserMapper.insertSelective(frontUser);
            if(i > 0){
                return CommonResult.ok(EmErrorCode.UPDATE_OK);
            }else{
                return CommonResult.ok(EmErrorCode.UPDATE_ERROR);
            }
        }else{
            return CommonResult.ok(EmErrorCode.UPDATE_ERROR);
        }
    }

    /**
     * @Author XMY
     * @Description 前台用户管理
     * @Date 2023/12/14 14:46
     * @Return
     * @param frontUser
     * @param pageRequest
     */
    @Override
    public CommonResult getFrontUserList(FrontUser frontUser, PageRequest pageRequest) {
        Date beginDate = null;
        Date endDate = null;
        String userName = frontUser.getUserName();
        String phone = frontUser.getPhone();
        Object beginTime = frontUser.getParams().get("beginTime");
        Object endTime = frontUser.getParams().get("endTime");
        try {
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            if (beginTime != null && endTime != null && StringUtils.isNotBlank(beginTime.toString()) && StringUtils.isNotBlank(endTime.toString())) {
                String beginStr = beginTime.toString() + " 00:00:00";
                String endStr = endTime.toString() + " 23:59:59";
                // 解析开始时间和结束时间
                beginDate = dateFormat.parse(beginStr);
                endDate = dateFormat.parse(endStr);
            }
            MybatisPageHelper.startPage(pageRequest);
            PageResult pageResult = MybatisPageHelper.getPageResult(frontUserMapper.getFrontUserList(userName, phone, beginDate, endDate));
            return CommonResult.ok(pageResult);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return CommonResult.ok();
    }

    /**
     * @Author XMY
     * @Description 导出接口
     * @Date 2023/12/15 14:00
     * @Return
     * @param response
     */
    @Override
    public void export(HttpServletResponse response) throws Exception {
        // 从数据库查询出所有的数据
        List<FrontUser> list = frontUserMapper.getFrontUserList(null, null, null, null);
        // 在内存操作，写出到浏览器
        //创建工作簿
        XSSFWorkbook workbook = new XSSFWorkbook();
        //创建工作表
        XSSFSheet sheet = workbook.createSheet("用户信息");
        //创建行，设置表头
        XSSFRow header = sheet.createRow(0);
        header.createCell(0).setCellValue("ID");
        header.createCell(1).setCellValue("用户名");
        header.createCell(2).setCellValue("个性签名");
        header.createCell(3).setCellValue("手机号");
        header.createCell(4).setCellValue("邮箱");
        header.createCell(5).setCellValue("昵称");
        header.createCell(6).setCellValue("创建时间");
        //遍历数据集合，将每一条数据写入Excel表格
        for (int i = 0; i < list.size(); i++) {
            FrontUser user = list.get(i);
            XSSFRow row = sheet.createRow(i + 1);
            row.createCell(0).setCellValue(user.getId());
            row.createCell(1).setCellValue(user.getUserName());
            row.createCell(2).setCellValue(user.getSignature());
            row.createCell(3).setCellValue(user.getPhone());
            row.createCell(4).setCellValue(user.getEmail());
            row.createCell(5).setCellValue(user.getUserAccount());
            row.createCell(6).setCellValue(user.getCreateTime().toString());
        }
        // 设置浏览器响应的格式和文件名
        response.setContentType("application/octet-stream;charset=utf-8");
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("用户信息.xlsx", "UTF-8"));
        // 将Excel文件输出到浏览器
        OutputStream out = response.getOutputStream();
        workbook.write(out);
        out.flush();
        out.close();
    }

    @Override
    public Boolean importData(MultipartFile file) throws Exception{
        InputStream inputStream = file.getInputStream();//获取一个输入流
        ExcelReader reader = ExcelUtil.getReader(inputStream);//读取这个输入流
        //忽略表头的中文，直接读取表的内容
        List<List<Object>> list = reader.read(1);
        List<FrontUser> users = CollUtil.newArrayList();
        for (List<Object> row : list) {
            FrontUser user = new FrontUser();
            user.setId(Integer.parseInt(row.get(0).toString()));
            user.setUserName(row.get(1).toString());
            user.setSignature(row.get(2).toString());
            user.setPhone(row.get(3).toString());
            user.setEmail(row.get(4).toString());
            user.setUserAccount(row.get(5).toString());
            String createTimeStr = (String) row.get(6);
            SimpleDateFormat dateFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", Locale.US);
            Date createTime;
            try {
                createTime = dateFormat.parse(createTimeStr);
                user.setCreateTime(createTime);
            } catch (ParseException e) {
                // 处理日期解析异常
                e.printStackTrace();
            }
            users.add(user);
        }
        frontUserMapper.insertList(users);
        return true;
    }
    /**
     * @Author LYX
     * @Description 用户修改密码
     * @Date 2024/3/20 16:11
     * @Return
     * @param frontUserModel
     */
    @Override
    public CommonResult updatePassword(FrontUserModel frontUserModel) {
        String openid=frontUserModel.getWxOpenid();
        FrontUser frontUser=frontUserMapper.getFrontUserByOpenId(openid);
        boolean matches = passwordEncoder.matches(frontUserModel.getOldPasswords(), frontUser.getUserPassword());
        if(matches){
            return CommonResult.ok(frontUserMapper.updatePassword(bCryptPasswordEncoder.encode(frontUserModel.getNewPasswords()),openid));
        }else {
            return CommonResult.error(404,"密码输入有误");
        }
    }
}
